package com.glacier.yuyuan.modules.admin.sys.service.impl;

import com.glacier.common.core.annotation.DataScope;
import com.glacier.common.core.constant.DictEnum;
import com.glacier.common.core.domain.Page;
import com.glacier.common.support.domain.UserInfo;
import com.glacier.common.support.service.impl.BaseServiceImpl;
import com.glacier.yuyuan.modules.admin.sys.domain.Role;
import com.glacier.yuyuan.modules.admin.sys.domain.User;
import com.glacier.yuyuan.modules.admin.sys.domain.UserRole;
import com.glacier.yuyuan.modules.admin.sys.mapper.RoleMapper;
import com.glacier.yuyuan.modules.admin.sys.mapper.UserMapper;
import com.glacier.yuyuan.modules.admin.sys.mapper.UserRoleMapper;
import com.glacier.yuyuan.modules.admin.sys.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.Serializable;
import java.util.List;
import java.util.stream.Collectors;

/**
 * date 2022-11-08 16:03
 * 用户业务层
 *
 * @author glacier
 * @version 1.0
 */
@Transactional(readOnly = true)
@Service
public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implements UserService, UserDetailsService {

    private UserRoleMapper userRoleMapper;

    private RoleMapper roleMapper;

    private PasswordEncoder passwordEncoder;

    public UserServiceImpl() {
        super(UserMapper.class);
    }

    @Autowired
    public void setUserRoleMapper(UserRoleMapper userRoleMapper) {
        this.userRoleMapper = userRoleMapper;
    }

    @Autowired
    public void setRoleMapper(RoleMapper roleMapper) {
        this.roleMapper = roleMapper;
    }

    @Autowired
    public void setPasswordEncoder(PasswordEncoder passwordEncoder) {
        this.passwordEncoder = passwordEncoder;
    }

    /**
     * 查询
     *
     * @param id
     * @return
     */
    @Override
    public <ID extends Serializable> User findById(ID id) {
        User entity = mapper.findById(id);
        entity.setRoleIdList(userRoleMapper.findListByUserId(id));
        return entity;
    }

    /**
     * 分页查询
     *
     * @param page
     * @param entity
     * @return
     */
    @DataScope()
    @Override
    public Page<User> findPage(Page<User> page, User entity) {
        return super.findPage(page, entity);
    }

    /**
     * 根据用户名查找
     *
     * @param username
     * @return
     */
    public User findByUsername(String username) {
        return mapper.findByUsername(username);
    }

    /**
     * 保存
     *
     * @param entity
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int save(User entity) {
        // 处理密码
        if (entity.getPassword() != null
            && !entity.getPassword().isBlank()) {
            entity.setPassword(passwordEncoder.encode(entity.getPassword()));
        }
        int update = super.save(entity);
        if (!entity.isNewRecordFlag()) {
            // 删除用户和角色关系
            userRoleMapper.deleteByUserId(entity.getId());
        }
        // 保存新的用户和角色关系
        if (!entity.getRoleIdList().isEmpty()) {
            userRoleMapper.batchInsert(
                entity.getRoleIdList()
                    .stream()
                    .map(officeId -> new UserRole(entity.getId(), officeId))
                    .collect(Collectors.toSet()));
        }
        return update;
    }

    /**
     * 删除
     *
     * @param idList
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public <ID extends Serializable> int batchDelete(List<ID> idList) {
        int delete = super.batchDelete(idList);
        if (!idList.isEmpty()) {
            // 删除用户和角色关系
            userRoleMapper.deleteByUserIds(idList);
        }
        return delete;
    }

    /**
     * 根据用户名查找
     *
     * @param username the username identifying the user whose data is required.
     * @return
     * @throws UsernameNotFoundException
     */
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = mapper.findByUsername(username);
        if (user == null || user.getId() == null || user.getId().isBlank()) {
            throw new UsernameNotFoundException("用户名或者密码错误！");
        }
        UserInfo userInfo = new UserInfo();
        userInfo.setId(user.getId());
        userInfo.setUsername(user.getUsername());
        userInfo.setPassword(user.getPassword());
        userInfo.setUserType(user.getUserType());
        //
        userInfo.setRoles(roleMapper.findByUserId(user.getId())
            .stream()
            .map(Role::getCode)
            .collect(Collectors.toList()));
        userInfo.setAccountNonExpired(true);
        userInfo.setAccountNonLocked(true);
        userInfo.setCredentialsNonExpired(true);
        userInfo.setEnabled(DictEnum.STATUS_NORMAL.getCode().equals(user.getStatus()));
        return userInfo;
    }
}
